#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <linux/input.h>
#include <sys/select.h>
#include <sys/time.h>

#include "ts.h"
// 获取触摸屏点击事件
void get_ts_point(ts_point *p)
{
  int ret;
  int fd;

  fd = open("/dev/input/event0", O_RDONLY);
  if (fd == -1)
  {
    perror("failed to open /dev/input/event0");
    return;
  }

  int x1 = -1, y1 = -1; // 记录点击事件中第一个点的坐标
  int x2 = 0, y2 = 0;   // 记录点出事件中最后一个点的坐标

  while (1)
  {
    struct input_event ev;
    ret = read(fd, &ev, sizeof(ev));
    if (ret != sizeof(ev))
    {
      continue;
    }

    // printf("type: %x  code: %x  value: %x\n", ev.type, ev.code, ev.value);

    // 触摸屏的x轴事件
    if (ev.type == EV_ABS && ev.code == ABS_X)
    {
      if (x1 == -1)
      {
        x1 = ev.value;
      }
      x2 = ev.value;
    }

    // 触摸屏的y轴事件
    if (ev.type == EV_ABS && ev.code == ABS_Y)
    {
      if (y1 == -1)
      {
        y1 = ev.value;
      }
      y2 = ev.value;
    }

    // 触摸屏弹起事件
    if ((ev.type == EV_KEY && ev.code == BTN_TOUCH && ev.value == 0) ||
        (ev.type == EV_ABS && ev.code == ABS_PRESSURE && ev.value == 0))
    {
      x1 = x1 * 800.0 / 1024;
      x2 = x2 * 800.0 / 1024;

      y1 = y1 * 480.0 / 600;
      y2 = y2 * 480.0 / 600;

      p->x = x2;
      p->y = y2;
      break;
    }
  }

  close(fd);
}

// 获取触摸屏点击事件（带超时）
// 返回值：1=成功获取触摸点，0=超时
int get_ts_point_timeout(ts_point *p, int timeout_ms)
{
  int ret;
  int fd;

  fd = open("/dev/input/event0", O_RDONLY);
  if (fd == -1)
  {
    perror("failed to open /dev/input/event0");
    return 0;
  }

  int x1 = -1, y1 = -1;
  int x2 = 0, y2 = 0;

  struct timeval start_time, current_time;
  gettimeofday(&start_time, NULL);

  // 设置为非阻塞模式
  int flags = fcntl(fd, F_GETFL, 0);
  fcntl(fd, F_SETFL, flags | O_NONBLOCK);

  while (1)
  {
    // 检查超时
    gettimeofday(&current_time, NULL);
    long elapsed_ms = (current_time.tv_sec - start_time.tv_sec) * 1000 +
                      (current_time.tv_usec - start_time.tv_usec) / 1000;

    if (elapsed_ms >= timeout_ms)
    {
      close(fd);
      return 0; // 超时
    }

    struct input_event ev;
    ret = read(fd, &ev, sizeof(ev));

    if (ret == -1)
    {
      if (errno == EAGAIN || errno == EWOULDBLOCK)
      {
        usleep(10000); // 10ms
        continue;
      }
      else
      {
        close(fd);
        return 0;
      }
    }

    if (ret != sizeof(ev))
    {
      continue;
    }

    // 触摸屏的x轴事件
    if (ev.type == EV_ABS && ev.code == ABS_X)
    {
      if (x1 == -1)
      {
        x1 = ev.value;
      }
      x2 = ev.value;
    }

    // 触摸屏的y轴事件
    if (ev.type == EV_ABS && ev.code == ABS_Y)
    {
      if (y1 == -1)
      {
        y1 = ev.value;
      }
      y2 = ev.value;
    }

    // 触摸屏弹起事件
    if ((ev.type == EV_KEY && ev.code == BTN_TOUCH && ev.value == 0) ||
        (ev.type == EV_ABS && ev.code == ABS_PRESSURE && ev.value == 0))
    {
      x1 = x1 * 800.0 / 1024;
      x2 = x2 * 800.0 / 1024;

      y1 = y1 * 480.0 / 600;
      y2 = y2 * 480.0 / 600;

      p->x = x2;
      p->y = y2;

      close(fd);
      return 1; // 成功
    }
  }
}

// 获取手指在触摸屏上的滑动方向
move_dir_t get_ts_direction(void)
{
  int ret;
  int fd;
  move_dir_t dir = MOVE_UNKNOWN;

  fd = open("/dev/input/event0", O_RDONLY);
  if (fd == -1)
  {
    perror("failed to open /dev/input/event0");
    return -1;
  }

  int x1 = -1, y1 = -1; // 记录点击事件中第一个点的坐标
  int x2 = 0, y2 = 0;   // 记录点出事件中最后一个点的坐标

  while (1)
  {
    struct input_event ev;
    ret = read(fd, &ev, sizeof(ev));
    if (ret != sizeof(ev))
    {
      continue;
    }

    // printf("type: %x  code: %x  value: %x\n", ev.type, ev.code, ev.value);

    // 触摸屏的x轴事件
    if (ev.type == EV_ABS && ev.code == ABS_X)
    {
      if (x1 == -1)
      {
        x1 = ev.value;
      }
      x2 = ev.value;
    }

    // 触摸屏的y轴事件
    if (ev.type == EV_ABS && ev.code == ABS_Y)
    {
      if (y1 == -1)
      {
        y1 = ev.value;
      }
      y2 = ev.value;
    }
    // 触摸屏弹起事件
    if ((ev.type == EV_KEY && ev.code == BTN_TOUCH && ev.value == 0) ||
        (ev.type == EV_ABS && ev.code == ABS_PRESSURE && ev.value == 0))
    {
      int delt_x = abs(x2 - x1);
      int delt_y = abs(y2 - y1);

      if (delt_x >= 2 * delt_y) // 满足该条件，判定为水平方向滑动
      {
        if (x2 > x1)
        {
          dir = MOVE_RIGHT;
        }
        else
        {
          dir = MOVE_LEFT;
        }

        break;
      }
      else if (delt_y >= 2 * delt_x)
      {
        if (y2 > y1)
        {
          dir = MOVE_DOWN;
        }
        else
        {
          dir = MOVE_UP;
        }
        break;
      }
      else
      {
        // 方向不明，请继续
        x1 = -1;
        y1 = -1;
      }
    }
  }

  //

  close(fd);

  return dir;
}
